package com.atguigu.gmall.order.receiver;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.rabbit.config.MqConst;
import com.atguigu.gmall.enums.model.OrderStatus;
import com.atguigu.gmall.enums.model.ProcessStatus;
import com.atguigu.gmall.order.model.OrderInfo;
import com.atguigu.gmall.order.service.OrderInfoService;
import com.rabbitmq.client.Channel;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Map;
import java.util.Stack;
import java.util.concurrent.TimeUnit;

/**
 * @author: atguigu
 * @create: 2023-06-27 11:56
 */
@Slf4j
@Component
public class OrderReceiver {
    @Autowired
    private OrderInfoService orderInfoService;

    @Autowired
    private RedisTemplate redisTemplate;


    /**
     * 监听延迟关闭订单消息,完成关闭订单
     *
     * @param orderId
     * @param message
     * @param channel
     */
    @SneakyThrows
    @RabbitListener(queues = MqConst.QUEUE_ORDER_CANCEL)
    public void processOrderCancel(Long orderId, Message message, Channel channel) {
        if (orderId != null) {
            //关闭订单
            log.info("[订单服务]监听到关闭订单消息:{}", orderId);
            orderInfoService.execExpiredOrder(orderId);
        }
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }

    /**
     * 监听订单支付消息,修改订单状态
     *
     * @param orderId 订单ID
     * @param channel
     * @param message
     */
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_PAYMENT_PAY, durable = "true"),
            value = @Queue(value = MqConst.QUEUE_PAYMENT_PAY, durable = "true"),
            key = MqConst.ROUTING_PAYMENT_PAY
    ))
    public void processPaySucess(Long orderId, Channel channel, Message message) {
        if (orderId != null) {
            log.info("[订单服务]监听订单支付成功消息:{}", orderId);
            //1.幂等性处理 redis set nx
            String key = "mq:" + orderId;
            Boolean flag = redisTemplate.opsForValue().setIfAbsent(key, orderId, 5, TimeUnit.SECONDS);
            if (!flag) {
                return;
            }
            //2.根据订单ID修改订单状态 将状态改为 已支付
            orderInfoService.updateOrderStatus(orderId, ProcessStatus.PAID);
            //TODO 3.发送消息通知库存系统锁定商品库存
            orderInfoService.sendLockStockMsg(orderId);
        }
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }


    /**
     * 监听库存系统锁定库存结果,根据订单对应商品锁定结果修改订单状态
     *
     * @param stockResult 格式{orderId:55, status:"DEDUCTED"}
     * @param channel
     * @param message
     */
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_WARE_ORDER, durable = "true"),
            value = @Queue(value = MqConst.QUEUE_WARE_ORDER, durable = "true"),
            key = MqConst.ROUTING_WARE_ORDER
    ))
    public void processLockStockResult(String stockResult, Channel channel, Message message) {
        if (StringUtils.isNotBlank(stockResult)) {
            log.info("[订单服务]监听扣减库存结果:{}", stockResult);
            //1.将监听到字符串转为Map
            Map map = JSON.parseObject(stockResult, Map.class);
            if (!CollectionUtils.isEmpty(map)) {
                Object orderId = map.get("orderId");
                Object status =  map.get("status");
                //2.根据扣减结果更新状态
                if ("DEDUCTED".equals(status)) {
                    //扣减库存成功 改为待发货状态
                    orderInfoService.updateOrderStatus(Long.valueOf(orderId.toString()), ProcessStatus.WAITING_DELEVER);
                } else {
                    //扣减库存失败 改为库存异常
                    orderInfoService.updateOrderStatus(Long.valueOf(orderId.toString()), ProcessStatus.STOCK_EXCEPTION);
                }
            }
        }
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }

}
